package com.cskaoyan.search.service;

import com.cskaoyan.search.dto.SearchResponse;
import com.cskaoyan.search.entity.ItemDocument;
import com.cskaoyan.search.form.SearchRequest;
import com.cskaoyan.search.repository.ProductRepository;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author gatsby
 * @since 2022/11/02 17:20
 */
public class ProductSearchServiceImpl implements ProductSearchService {

    @Autowired
    ProductRepository productRepository;

    @Autowired
    ElasticsearchRestTemplate restTemplate;

    @Autowired
    RestHighLevelClient client;

    /**
     *
     * @param request 
     * @return com.cskaoyan.search.dto.SearchResponse
     * @author gatsby
     * @since 2022/11/02 22:37 
     */
    @Override
    public SearchResponse search(SearchRequest request) {
        //获取搜索的关键词
        @NotNull String key = request.getKey();
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        //构造bool查询中的match查询
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("title", key);
        //将该查询加入bool查询的must中
        boolQueryBuilder.must(matchQuery);

        //构造布尔查询中的范围查询
        RangeQueryBuilder priceRange = QueryBuilders.rangeQuery("price");
        if(request.getPriceGt()!=null && !"".equals(request.getPriceGt())){
            priceRange.gte(request.getPriceGt());
        }
        if(request.getPriceLte() !=null && !"".equals(request.getPriceLte())){
            priceRange.gt(request.getPriceLte());
        }
        //将范围查询添加到NativeSearchQueryBuilder
        boolQueryBuilder.filter(priceRange);

        //构造分页参数
        PageRequest pageRequest=null;
        if(request.getSort()!=null && !"".equals(request.getSort())){
            if(request.getSort().equals("-1")){
                pageRequest = PageRequest.of(request.getPage() - 1, request.getSize(),Sort.by(Sort.Order.desc("price")));
            }else if(request.getSort().equals("1")){
                pageRequest = PageRequest.of(request.getPage() - 1, request.getSize(),Sort.by(Sort.Order.asc("price")));
            }
        }else{
            pageRequest = PageRequest.of(request.getPage() - 1, request.getSize());
        }
        queryBuilder.withPageable(pageRequest);

        //构造高亮参数
        /*HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title").preTags("<font color='red'>").postTags("</font>");
        // 向NativeSearchQueryBuilder添加高亮参数
        queryBuilder.withHighlightBuilder(highlightBuilder);*/



        NativeSearchQuery build = queryBuilder.build();
        SearchHits<ItemDocument> searchHits = restTemplate.search(build, ItemDocument.class);
        List<ItemDocument> itemDocuments = new ArrayList<>();
        searchHits.forEach(hit->{
            ItemDocument content=hit.getContent();
            itemDocuments.add(content);
        });
        SearchResponse<ItemDocument> searchResponse = new SearchResponse<>();
        searchResponse.setData(itemDocuments);
        searchResponse.setTotal(Long.valueOf(itemDocuments.size()));
        return searchResponse;
    }

    /**
     * 模糊查询的业务逻辑
 * @param request
     * @return com.cskaoyan.search.dto.SearchResponse
     * @author gatsby
     * @since 2022/11/02 17:20
     */
    @Override
    public SearchResponse fuzzySearch(SearchRequest request) {
        @NotNull String key = request.getKey();
        //List<ItemDocument> itemDocuments = productRepository.matchSearch(key);
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        //构造bool查询中的wildcardQuery
        WildcardQueryBuilder wildcardQuery = QueryBuilders.wildcardQuery("title", "*" + key + "*");
        boolQueryBuilder.must(wildcardQuery);
        //TODO:高亮显示未设置

        //将bool查询添加到NativeSearchQueryBuilder
        queryBuilder.withQuery(boolQueryBuilder);

        NativeSearchQuery build = queryBuilder.build();
        SearchHits<ItemDocument> searchHits = restTemplate.search(build, ItemDocument.class);
        List<ItemDocument> itemDocuments = new ArrayList<>();
        searchHits.forEach(hit -> {
            ItemDocument content=hit.getContent();
            itemDocuments.add(content);
        });
        SearchResponse<ItemDocument> searchResponse = new SearchResponse<>();
        searchResponse.setTotal(Long.valueOf(itemDocuments.size()));
        searchResponse.setData(itemDocuments);
        return searchResponse;
    }
}
